home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Atari Mega Archive 1
/
Atari Mega Archive - Volume 1.iso
/
gnu
/
gnulib
/
libsrc98.zoo
/
doprnt.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-11-05
|
28KB
|
1,226 lines
/*
* Copyright (c) 1988 Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms are permitted
* provided that the above copyright notice and this paragraph are
* duplicated in all such forms and that any documentation,
* advertising materials, and other materials related to such
* distribution and use acknowledge that the software was developed
* by the University of California, Berkeley. The name of the
* University may not be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
/*
* minorly customized for gcc lib
* ++jrb
* and for the sfp004 as well as the TT's 68881
* mjr++
* and for turbo C and the MiNT library
* ++um,mh
* and special M68881 and sfp004 version of cvt() added that uses fmovep for
* maximum precision, no bits lost anymore!
* ++schwab
*/
#ifndef __NO_FLOAT__
#if 0
static unsigned long
__notanumber[2] = { 0x7fffffffL, 0xffffffffL }; /* ieee NAN */
#define NAN (*((double *)&__notanumber[0]))
static unsigned long
__p_infinity[2] = { 0x7ff00000L, 0x00000000L }; /* ieee NAN */
#define INF (*((double *)&__p_infinity[0]))
#endif
#define NAN_HI 0x7fffffffL
#define NAN_LO 0xffffffffL
#define INF_HI 0x7ff00000L
#define INF_LO 0x00000000L
#endif /* __NO_FLOAT__ */
#ifdef LIBC_SCCS
static char sccsid[] = "@(#)doprnt.c 5.37 (Berkeley) 3/26/89";
#endif /* LIBC_SCCS */
#include <compiler.h>
#ifdef __TURBOC__
#include <sys\types.h>
#else
#include <sys/types.h>
#endif
#include <stdarg.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <limits.h>
#include <math.h> /* mjr++ */
#include "lib.h"
#ifndef __GNUC__ /* gcc lib has these typedefs in sys/types.h */
#ifndef __MINT__ /* as does the MiNT library */
typedef unsigned char u_char;
typedef unsigned long u_long;
#endif
#endif
/* 11-bit exponent (VAX G floating point) is 308 decimal digits */
#define MAXEXP 308
/* 128 bit fraction takes up 39 decimal digits; max reasonable precision */
# define MAXFRACT 39
# define MAXEXP 308
#if defined (__M68881__) && !defined (sfp004)
# include <math-68881.h> /* mjr: use the inline functions */
#endif /* __M68881__ */
#define DEFPREC 6
#define BUF (MAXEXP+MAXFRACT+1) /* + decimal point */
#define PUTC(ch) if( (*putfunc)(ch, fp) == EOF ) return EOF;
#ifdef PRINTF_LONGLONG
#define ARG(signtag) (\
(flags&LONGLONG ? \
(_ulonglong = (unsigned long long)va_arg(argp, signtag long long)) : 0 ) ,\
_ulong = \
flags&LONGLONG ? \
_ulonglong != 0ll : \
flags&LONGINT ? \
(unsigned long long)va_arg(argp, signtag long) : \
(flags&SHORTINT ? \
(unsigned long long)(signtag short)va_arg(argp, signtag int) : \
(unsigned long long)va_arg(argp, signtag int)) )
/* shorts are always promoted to ints; thus, it's `va_arg(... int)'
* for `flags&SHORTINT'!
*/
#else
#define ARG(signtag) \
_ulong = \
flags&LONGINT ? \
(unsigned long)va_arg(argp, signtag long) : \
(flags&SHORTINT ? \
(unsigned long)(signtag short)va_arg(argp, signtag int) : \
(unsigned long)va_arg(argp, signtag int))
/* shorts are always promoted to ints; thus, it's `va_arg(... int)'
* for `flags&SHORTINT'!
*/
#endif
#define TEN_MUL(X) ((((X) << 2) + (X)) << 1)
#define todigit(c) ((c) - '0')
#define tochar(n) ((n) + '0')
#define LONGINT 0x01 /* long integer */
#define LONGLONG 0x02 /* long long integer (8 bytes) */
#define LONGDBL 0x04 /* long double; unimplemented */
#define SHORTINT 0x08 /* short integer */
#define ALT 0x10 /* alternate form */
#define LADJUST 0x20 /* left adjustment */
#define ZEROPAD 0x40 /* zero (as opposed to blank) pad */
#define HEXPREFIX 0x80 /* add 0x or 0X prefix */
#ifndef __NO_FLOAT__
#define __FLOATS__ 1
#endif
#ifdef __FLOATS__
# include "flonum.h"
#if defined (__M68881__) || defined (sfp004)
static char *exponent __PROTO ((char *, int, int));
static int _round __PROTO ((int, char *, char *, char *));
static int cvt __PROTO ((double, int, int, char *, int, char *));
#else
# if __STDC__
static char *exponent(char *, int, int);
static char *_round(double, int *, char *, char *, int, char *);
static int cvt(double, int, int, char *, int, char *, char *);
# else
static char *exponent();
static char *_round();
static int cvt();
# endif
#endif /* __M68881__ */
#endif
#if defined(__GNUC__) && (!defined(__NO_INLINE__))
#ifdef __M68020__
#define _ICONV(NUMBER, BASE, BUF) \
{ \
long i; \
do \
{ \
__asm__ volatile \
("divull %3,%1:%0" \
: "=d"((long)(NUMBER)), "=d"(i) \
: "0"((long)(NUMBER)), "d"((long)(BASE))); \
*--(BUF) = digs[i]; \
} \
while (NUMBER); \
}
#else /* !__M68020 */
#define _ICONV(NUMBER, BASE, BUF) \
{ \
\
while((NUMBER) > 65535L) \
{ \
extern unsigned long __udivsi3(); /* quot = d0, rem = d1 */ \
register long i __asm ("d1"); \
__asm__ volatile("
movl %3,sp@-;
movl %2,sp@-;
jsr ___udivsi3;
addqw #8,sp;
movl d0,%0" \
: "=r"((long)NUMBER), "=d"(i) \
: "0"((long)NUMBER), "r"((long)BASE) \
: "d0", "d1", "a0", "a1"); \
*--BUF = digs[i]; \
} \
do \
{ \
short i; \
__asm__ volatile("
divu %3,%2;
swap %0;
movw %0,%1;
clrw %0;
swap %0" \
: "=d"((long)NUMBER), "=g"(i) \
: "0"((long)NUMBER), "dm"((short)BASE)); \
*--BUF = digs[i]; \
} while(NUMBER); \
}
#endif /* __M68020 */
#else /* !__GNUC__ */
#define _ICONV(NUMBER, BASE, BUF) \
do { \
*--(BUF) = digs[(NUMBER) % (BASE)]; \
(NUMBER) /= (BASE); \
} while (NUMBER);
#endif /* __GNUC__ */
#ifdef PRINTF_LONGLONG
#define _ICONVLL(NUMBER, BASE, BUF) \
do { \
*--(BUF) = digs[(NUMBER) % (BASE)]; \
(NUMBER) /= (BASE); \
} while (NUMBER);
#endif
int _doprnt(putfunc, fp, fmt0, argp)
int (*putfunc) __PROTO ((int, FILE *));
FILE *fp;
const char *fmt0;
va_list argp;
{
register const u_char *fmt; /* format string */
register int ch; /* character from fmt */
register int cnt; /* return value accumulator */
register int n; /* random handy integer */
register char *t; /* buffer pointer */
#ifdef __FLOATS__
/* double _double; *//* double precision arguments %[eEfgG] */
union double_di _dd; /* _double is #defined to be _dd later on */
char softsign; /* temporary negative sign for floats */
#endif /* __FLOATS__ */
#ifdef PRINTF_LONGLONG
typedef unsigned long long _ulonglongtype;
typedef long long _ulonglongsignedtype;
_ulonglongtype _ulonglong;
#endif
typedef u_long _ulongtype;
typedef long _ulongsignedtype;
_ulongtype _ulong; /* integer arguments %[diouxX] */
short base; /* base for [diouxX] conversion */
short dprec; /* decimal precision in [diouxX] */
short fieldsz; /* field size expanded by sign, etc */
short flags; /* flags as above */
short fpprec; /* `extra' floating precision in [eEfgG] */
short prec; /* precision from format (%.3d), or -1 */
short realsz; /* field size expanded by decimal precision */
short size; /* size of converted field or string */
short width; /* width from format (%8d), or 0 */
char sign; /* sign prefix (' ', '+', '-', or \0) */
char *digs; /* digits for [diouxX] conversion */
char buf[BUF]; /* space for %c, %[diouxX], %[eEfgG] */
fmt = (const u_char *) fmt0;
digs = "0123456789abcdef";
for (cnt = 0;; ++fmt) {
if ((ch = *fmt) == 0)
return (cnt);
if (ch != '%') {
PUTC(ch);
cnt++;
continue;
}
flags = 0; dprec = 0; fpprec = 0; width = 0;
prec = -1;
sign = '\0';
rflag: switch (*++fmt) {
case ' ':
/*
* ``If the space and + flags both appear, the space
* flag will be ignored.''
* -- ANSI X3J11
*/
if (!sign)
sign = ' ';
goto rflag;
case '#':
flags |= ALT;
goto rf